package typoker.logic;

import typoker.utils.Util;

public class Evaluator {
	private static final short[] hash_adjust = Util.readShortFromFile("hash_adjust.dat");
	private static final short[] hash_values = Util.readShortFromFile("hash_values.dat");
	private static final short[] flushes = Util.readShortFromFile("flushes.dat");
	private static final short[] unique5 = Util.readShortFromFile("unique5.dat");

	private Evaluator() {}

	public synchronized static int evaluate(Card c1, Card c2, Card c3, Card c4,
			Card c5) {
		return evaluateHand(c1.getValue(), c2.getValue(), c3.getValue(),
				c4.getValue(), c5.getValue());
	}

	public static String valueToText(int value) {
		String text = "";

		if (value > 6185) {
			text = "High Card";
		} else if (value > 3325) {
			text = "One Pair";
		} else if (value > 2467) {
			text = "Two Pair";
		} else if (value > 1609) {
			text = "Three of a Kind";
		} else if (value > 1599) {
			text = "Straight";
		} else if (value > 322) {
			text = "Flush";
		} else if (value > 166) {
			text = "Full House";
		} else if (value > 10) {
			text = "Four of a Kind";
		} else if (value > 1) {
			text = "Straight Flush";
		} else if (value == 1) {
			text = "Royal Flush";
		} else {
			text = "Invalid value";
		}

		return text;
	}

	private static int evaluateHand(int c1, int c2, int c3, int c4, int c5) {
		int q = (c1 | c2 | c3 | c4 | c5) >>> 16;

		if ((c1 & c2 & c3 & c4 & c5 & 0xf000) != 0) {
			return flushes[q];
		}

		short s = unique5[q];
		if (s != 0) {
			return s;
		}

		return hash_values[findFast((c1 & 0xff) * (c2 & 0xff) * (c3 & 0xff)
				* (c4 & 0xff) * (c5 & 0xff))];
	}

	private static int findFast(int u) {
		u += 0xe91aaa35;
		u ^= u >>> 16;
		u += u << 8;
		u ^= u >>> 4;

		int b = (u >>> 8) & 0x1ff;
		int a = (u + (u << 2)) >>> 19;
		int r = a ^ hash_adjust[b];

		return r;
	}
}
